package comp353Games;


/**
 * Snort describes a game of Snort.  More information about this game is 
 *  available here: http://en.wikipedia.org/wiki/Snort
 * 
 * @author Tyler Radley, Andre Harvey, Deanna Fink 
 * @version February 13, 2012
 */


public class Game {

    // instance variables 
    
    /**
     * The error message to be printed if an error arises
     */
    private String errorMessage;
        
    /**
     * A constant representing Player 1 
     */
    public static final int PLAYER_ONE = 1;
    
    /**
     * A constant representing Player 1 
     */
    public static final int PLAYER_TWO = 2;
    
    /**
     * An array of sections of connected nodes
     */
    private int[][] rows;
    
    /**
     * An array of the lengths of each row of nodes
     */
    private int[] rowSizes;
    

    /**
     * Constructor for a default basic game with four rows of sizes 3, 5, and 7 
     */
    public Game() {
        
    } 
    
    /**
     * Returns the current error message
     * 
     * @return      The current error message
     */
    public String getErrorMessage(){
        return this.errorMessage;
    }
    
     /**
     * Returns a hash code for this game.
     * 
     * @return      A hash code for this game.
     */
    @Override
    public int hashCode() {
        int code = 0;
        for (int i = 0; i < this.rows.length; i++) {
            code += (this.rows[i].length + 1) * Math.pow(3, i);
        }
        return code;
    }
    
    /**
     * Determines whether there are any positions for the Left player to move to.
     *  
     * @return           Whether this game has any moves for the Left player.
     */
    public boolean hasMovesLeft(int player) {
    	boolean displayErrors = false;
        for (int i = 0; i < rowSizes.length; i++) {
            if (validRow(i,player,displayErrors)){
                    return true;
            }
        }
        return false;
    }
    
//    /**
//     * Updates the game for the next move
//     * 
//     * @param rows          The chosen row.
//     * @param cell          The chosen cell.
//     * @return              A new game updated with all the moves made.
//     */
//    public Game move( int row,int cell, int player){
// 
//    }
//    
    /**
     * Returns a string version of this.
     * 
     * @param indent    The indentation between the edge of the window and the text.
     * @return          A string version of the game indented from the margin. 
     */
    public String toString(String indent) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(indent + "Snort\n");
        stringBuffer.append(indent + "|");
        for (int i = 0; i < this.rowSizes.length; i++) {
            for(int j = 0; j < rowSizes[i]; i++){
                stringBuffer.append(" ");
                if (rows[i][j] == -1) {
                    stringBuffer.append("B");
                } else if (rows[i][j] == 0) {
                    stringBuffer.append(" ");
                } else if (rows[i][j] == 1) {
                    stringBuffer.append("R");
                } else {
                    //this case should never happen.  If we reach this, something went logically wrong!
                    //stringBuffer.append(rows[i][j]);
                }
            }
            stringBuffer.append(" |");
        }
        stringBuffer.append("\n");
        return stringBuffer.toString();
    }
    
    /**
     * Returns a string version of this.
     * 
     * @return     The string version of the game without an indentation.
     */
    @Override
    public String toString() {
        return this.toString("");
    }
    
    /** 
     * Checks whether the selected cell exists and is a valid move for the current player.
     * @param   rowIndex        The chosen row.
     * @param   nodeIndex       The chosen cell.
     * @param   player          The code identifying the current player.
     * @param   displayErrors   Denotes whether the function should display errors or not. 
     * 
     * @return  Whether the selected cell exists and is a valid move for the current player.
     */
    public boolean validNode(int nodeIndex, int rowIndex, int player, boolean displayErrors){
    	int otherPlayerColor;
        this.errorMessage = "";
    	if (player == PLAYER_ONE){
    		otherPlayerColor = PLAYER_TWO;
    	}
    	else{
    		otherPlayerColor = PLAYER_ONE;
    	}
        if(nodeIndex < 0 || nodeIndex >= rowSizes[rowIndex]){
            if (displayErrors){
                   this.errorMessage = "Invalid Index";
            }
            return false;
    	}
    	if(rows[rowIndex][nodeIndex] != 0){
            if (displayErrors){
                this.errorMessage = "This node has already been colored in!";
            }
            return false;
        }
    	else{
            if (nodeIndex > 0){
                if (rows[rowIndex][nodeIndex - 1] == otherPlayerColor){
                    if (displayErrors){
                        this.errorMessage = "You can't pick a node adjacent to the other player's node";
                    }
                    return false;
                }
            }
            if (nodeIndex < (rows[rowIndex].length -1)){
                if (rows[rowIndex][nodeIndex + 1] == otherPlayerColor){
                    if (displayErrors){
                        this.errorMessage = "You can't pick a node adjacent to the other player's node";
                    }
                    return false;
                }
            }
    	}
    	return true;
    }
    
    /** 
     * Checks whether the selected row exists and has valid moves for the current player.
     * @param   rowIndex        The chosen row
     * @param   player          The code identifying the current player.
     * @param   displayErrors   Denotes whether the function should display errors or not. 
     * 
     * @return  Whether the selected row exists and has valid moves for the current player.
     */
    public boolean validRow(int rowIndex, int player, boolean displayErrors){
        if (rowIndex < 0 || rowIndex >= this.rowSizes.length){
            return false;
        }else{
            for (int i = 0; i < rowSizes[rowIndex]; i++){
                if (validNode(i, rowIndex, player, displayErrors)){
                        return true;
                }
            }
        }
        return false;
    }
}
